﻿namespace Probel.NDoctor.Statistics.UnitTests
{
    using System;
    using System.Linq;

    using NUnit.Framework;

    using Probel.NDoctor.Statistics.Domain;
    using Probel.NDoctor.Statistics.UnitTests.Helpers;

    [TestFixture]
    public abstract class BaseChartQuery
    {
        #region Fields

        private readonly IFactory Factory;

        #endregion Fields

        #region Constructors

        public BaseChartQuery(IFactory factory)
        {
            this.Factory = factory;
        }

        #endregion Constructors

        #region Methods

        [Test]
        public void GetChart_Bottlenecks_9Found()
        {
            var guid = Guid.NewGuid();
            this.AddBottlenecks(guid);
            var chart = this.Factory.Charts().GetBottlenecks();

            var result = (from point in chart
                          where point.Item1 == "aaa.aa"
                          select point).Single();
            Assert.AreEqual(9, result.Item2);
        }

        [Test]
        public void GetChart_ExecutionTime_5Elements()
        {
            var chart = this.Factory.Charts().GetExecutionTimeGraph();
            Assert.AreEqual(1, chart.Count());

            foreach (var item in chart)
            {
                Assert.AreEqual(10, item.Item2);
            }
        }

        [Test]
        public void GetChart_OfAvgExecutionTime_ByComponent()
        {
            var chart = this.Factory.Charts().GetAvgExecutionTimeByComponent();
            Assert.AreEqual(10, chart.Count());

            foreach (var item in chart)
            {
                Assert.AreEqual((double)10 / 1000, item.Item2);
            }
        }

        [Test]
        public void GetChart_OfAvgExecutionTime_ByMethod()
        {
            var chart = this.Factory.Charts().GetAvgExecutionTimeByComponent();
            Assert.AreEqual(10, chart.Count());

            foreach (var item in chart)
            {
                Assert.AreEqual((double)10 / 1000, item.Item2);
            }
        }

        [Test]
        public void GetChart_OfBottlenecks_5Elements()
        {
            var chart = this.Factory.Charts().GetBottlenecks();
            Assert.AreEqual(5, chart.Count());

            foreach (var item in chart)
            {
                Assert.AreEqual(1, item.Item2);
            }
        }

        [Test]
        public void GetChart_OfSessionDurations_XElements()
        {
            var result = this.Factory.Charts().GetSessionDurations();
            Assert.AreEqual(10, result.Count());
        }

        [Test]
        public void GetChart_OfSessionDuration_1Element()
        {
            var chart = this.Factory.Charts().GetSessionDurations();

            Assert.AreEqual(10, chart.Count());
            foreach (var point in chart) { Assert.AreEqual(new TimeSpan(0, 15, 0).TotalMinutes, point.Item2); }
        }

        [Test]
        public void GetChart_OfUsageByComponent_1Elements()
        {
            var chart = this.Factory.Charts().GetExecutionTimeGraph();
            Assert.AreEqual(1, chart.Count());

            foreach (var item in chart)
            {
                Assert.AreEqual(10, item.Item2);
            }
        }

        [Test]
        public void GetChart_OfUsageByMethod_1Elements()
        {
            var chart = this.Factory.Charts().GetExecutionTimeGraph();
            Assert.AreEqual(1, chart.Count());

            foreach (var item in chart)
            {
                Assert.AreEqual(10, item.Item2);
            }
        }

        [SetUp]
        public void _Setup()
        {
            this.Factory.Exporter().ClearRepository();
            Factory.Import(Data.Applications, Data.Statistics, Data.Durations);
        }

        private void AddBottlenecks(Guid guid)
        {
            this.Factory.Exporter().Insert(new Application()
            {
                ApplicationKey = guid,
            });
            var app = this.Factory.Scalars().GetApplicationByAppKey(guid);

            // These are bottlenecks
            for (int i = 0; i < 9; i++)
            {
                this.Factory.Exporter().Insert(new StatisticEntry()
                {
                    Application = app,
                    ExecutionTime = 10,
                    IsPossibleBottleneck = true,
                    MethodName = "aa",
                    TargetTypeName = "aaa",
                    Threshold = 5,
                    TimeStamp = DateTime.Now,
                    Version = "1.0.0.0"
                });

                //This is NOT a bottleneck
                this.Factory.Exporter().Insert(new StatisticEntry()
                {
                    Application = app,
                    ExecutionTime = 1,
                    IsPossibleBottleneck = false,
                    MethodName = "aa",
                    TargetTypeName = "aaa",
                    Threshold = 5,
                    TimeStamp = DateTime.Now,
                    Version = "1.0.0.0"
                });
            }
        }

        #endregion Methods
    }
}